
package financedata.historicalquotes;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

/**
 *
 * @author Stijn Strickx
 */
public class YahooRequest implements IHistoryRequest {
    
    public static final String HISTQUOTES_BASE_URL = "http://ichart.yahoo.com/table.csv"; 
    private final String symbol;
    
    private final Calendar from;
    private final Calendar to;
    
    private final Interval interval;

    public static final Calendar DEFAULT_FROM = Calendar.getInstance();
    static {
        DEFAULT_FROM.add(Calendar.YEAR, -1);
    }
    public static final Calendar DEFAULT_TO = Calendar.getInstance();
    public static final Interval DEFAULT_INTERVAL = Interval.MONTHLY;
    
    YahooRequest(String symbol) {
        this(symbol, DEFAULT_INTERVAL);
    }
    
    YahooRequest(String symbol, Interval interval) {
        this.symbol = symbol;
        this.interval = interval;
        
        this.from = DEFAULT_FROM;
        this.to = DEFAULT_TO;
    }
    
    YahooRequest(String symbol, Calendar from, Calendar to) {
        this(symbol, from, to, DEFAULT_INTERVAL);
    }
    
    YahooRequest(String symbol, Calendar from, Calendar to, Interval interval) {
        this.symbol = symbol;
        this.from = from;
        this.to = to;
        this.interval = interval;
    }
    
    YahooRequest(String symbol, Date from, Date to) {
        this(symbol, from, to, DEFAULT_INTERVAL);
    }
    
    YahooRequest(String symbol, Date from, Date to, Interval interval) {
        this(symbol, interval);
        this.from.setTime(from);
        this.to.setTime(to);
    }
    
    public List<HistoricalQuote> getResult() {
        
        List<HistoricalQuote> result = new ArrayList<HistoricalQuote>();
        
        try {
            Map<String, String> params = new LinkedHashMap<String, String>();
            params.put("s", this.symbol);
            
            params.put("a", String.valueOf(this.from.get(Calendar.MONTH)));
            params.put("b", String.valueOf(this.from.get(Calendar.DAY_OF_MONTH)));
            params.put("c", String.valueOf(this.from.get(Calendar.YEAR)));
            
            params.put("d", String.valueOf(this.to.get(Calendar.MONTH)));
            params.put("e", String.valueOf(this.to.get(Calendar.DAY_OF_MONTH)));
            params.put("f", String.valueOf(this.to.get(Calendar.YEAR)));
            
            params.put("g", this.interval.getYahooTag());
            
            params.put("ignore", ".csv");
            
            String url = HISTQUOTES_BASE_URL + "?" + Utils.getURLParameters(params);
            
            // Get CSV from Yahoo
            Utils.logger.log(Level.INFO, ("Sending request: " + url));
            
            URL request = new URL(url);
            URLConnection connection = request.openConnection();
            InputStreamReader is = new InputStreamReader(connection.getInputStream());
            BufferedReader br = new BufferedReader(is);
            br.readLine(); // skip the first line
            // Parse CSV
            for(String line = br.readLine(); line != null; line = br.readLine()) { 
                HistoricalQuote quote = this.parseCSVLine(line);
                result.add(quote);
            }
            Utils.logger.log(Level.INFO, ("Get result.size=" + result.size()));
        } catch (IOException ex) {
            Utils.logger.log(Level.SEVERE, ex.toString(), ex);
        }
        return result;
    }
    
    private HistoricalQuote parseCSVLine(String line) {
        String[] data = line.split(Utils.QUOTES_CSV_DELIMITER);
        return new HistoricalQuote(this.symbol,
                Utils.parseHistDate(data[0]),
                Utils.getBigDecimal(data[1]),
                Utils.getBigDecimal(data[2]),
                Utils.getBigDecimal(data[3]),
                Utils.getBigDecimal(data[4]),
                Utils.getBigDecimal(data[6]),
                Utils.getLong(data[5])
        );
    }
    
}
